#ifndef PRYN_TOTAL_COMMANDER_H
#define PRYN_TOTAL_COMMANDER_H

#include <pryn.h>
#include <windows.h>

typedef struct TotalCommanderPlugin TotalCommanderPlugin;
typedef enum TotalCommanderCapabilities TotalCommanderCapabilities;
typedef struct TotalCommanderOpenArchiveData TotalCommanderOpenArchiveData;
typedef struct TotalCommanderHeaderData TotalCommanderHeaderData;

#define PrynStandardCall __stdcall

/// Capabilities mask for plugins.
enum TotalCommanderCapabilities
{
	TotalCommanderCapabilities_New = 1, /// Can create new archives; PackFiles should be non-null.
	TotalCommanderCapabilities_Modify = 2, /// Can modify existing archives; PackFiles should be non-null.
	TotalCommanderCapabilities_Multiple = 4, /// Archive contains multiple files; PackFiles may be given more than one file.
	TotalCommanderCapabilities_Delete = 8, /// Can delete files; DeleteFiles should be non-null.
	TotalCommanderCapabilities_Options = 16, /// Has an options dialog (ConfigurePacker should be non-null).
	TotalCommanderCapabilities_MemoryPacking = 32, /// Supports packing in memory; StartMemPack, PackToMem and DoneMemPack should be non-null.
	TotalCommanderCapabilities_ByContent = 64, /// Detects archive type by content; CanYouHandleThisFile should be non-null.
	TotalCommanderCapabilities_SearchText = 128, /// Allow searching for text in archives.
	TotalCommanderCapabilities_Hide = 256, /// Don't show packer icon, don't open with Enter, open with Control-PageDown.
};

struct TotalCommanderPlugin
{
	HMODULE library; /// Handle to the library.
	TotalCommanderCapabilities PrynStandardCall (*getPackerCaps) (); /// Get packer capabilities.
	void PrynStandardCall (*configurePacker) (HWND parent, HINSTANCE instance); /// Display a dialog box for configuring the packer, or a message box describing the packer.
	HANDLE PrynStandardCall (*openArchive) (TotalCommanderOpenArchiveData *info); /// Open archive, returning handle to it or 0 on failure.
	int PrynStandardCall (*readHeader) (HANDLE archive, TotalCommanderHeaderData *data); /// Read the next file's header or return TotalCommanderResult_EndOfArchive if done.
};

enum
{
	TotalCommanderOpenMode_List = 0, /// Open file for reading file names only.
	TotalCommanderOpenMode_Extract = 1, /// Open file for processing (extraction, testing).
};

enum TotalCommandResult
{
	TotalCommandResult_Success = 0, /// Success.
	TotalCommandResult_EndArchive = 10, /// No more files in the archive.
	TotalCommandResult_NoMemory = 11, /// Not enough memory.
	TotalCommandResult_BadData = 12, /// Data is bad.
	TotalCommandResult_BadArchive = 13, /// CRC error in archive data.
	TotalCommandResult_UnknownFormat = 14, /// Archive format is unknown.
	TotalCommandResult_CannotOpen = 15, /// Cannot open existing file.
	TotalCommandResult_CannotCreate = 16, /// Cannot create file.
	TotalCommandResult_CannotClose = 17, /// Error closing file.
	TotalCommandResult_CannotRead = 18, /// Error reading from file.
	TotalCommandResult_CannotWrite = 19, /// Error writing to file.
	TotalCommandResult_SmallBuffer = 20, /// Buffer is too small.
	TotalCommandResult_Aborted = 21, /// Function aborted by user.
	TotalCommandResult_NoFiles = 22, /// No files found.
	TotalCommandResult_TooManyFiles = 23, /// Too many files to pack.
	TotalCommandResult_NotSupported = 24, /// Function is not supported.
};

/// Information passed to OpenArchive.
struct TotalCommanderOpenArchiveData
{
	char *filename;
	int openMode; /// Either TotalCommanderOpenMode_List or TotalCommanderOpenMode_Extract.
	int openResult; /// Output from packer.
	char *commentBuffer; /// Optionally output from packer - may be null.
	int commentBufferSize; /// Total size of the comment buffer or 0 for none.
	int commentSize; /// Output size of the comment.
	int commentState; /// Whether a comment was written?
};

/// Mask of file attributes.
enum TotalCommanderAttribute
{
	TotalCommanderAttribute_ReadOnly = 1, /// Read-only.
	TotalCommanderAttribute_Hidden = 2, /// Hidden.
	TotalCommanderAttribute_System = 4, /// System file.
	TotalCommanderAttribute_VolumeIdentifier = 8, /// Volume identifier file.
	TotalCommanderAttribute_Directory = 0x10, /// Directory.
	TotalCommanderAttribute_Archive = 0x20, /// Archived file.
	TotalCommanderAttribute_Mask = 0x3F, /// Mask of all attributes.
};

/// Information passed to/from ReadHeader.
struct TotalCommanderHeaderData
{
	char archiveName [260]; /// Name of the archive.
	char fileName [260]; /// Name of the file.
	int flags; /// Appears unused.
	int packedSize; /// Size of the file in the package in bytes.
	int unpackedSize; /// Size of the unpacked file in bytes.
	int hostOs; /// Unused.
	int fileCrc; /// 32-bit CRC of the file or zero if there is none.
	int time; /// Date and time of the last modification, in the form ((year - 1980) << 25 | month << 21 | day << 16 | hour << 11 | minute << 5 | second / 2).
	int unpackedVersion; /// Unknown.
	int method; /// Packing method?
	int attributes; /// Attributes, bitmask of TotalCommanderAttribute.
	char *commentBuffer; /// (in) Optional comment buffer.
	int commentBufferSize; /// (in) Total size of the comment buffer.
	int commentSize; /// Written size of the comment buffer. 
	int commentState; /// Unknown.
};


#endif /* PRYN_TOTAL_COMMANDER_H */
